/*
硬件I2C驱动SHT30，读取温度
目前遇到过一大问题：原本调通过的程序放着不管，过一段时间后就不行了，读或写都会返回错误码80001314，SCL和SDA换一下也不
行，在进行排查后发现SCL引脚一直被拉低，用逻辑分析仪看发出去的全是0。最终它似乎自己突然就能用了，也不知道到底为什么，
总之这样就好。
关于I2C引脚的分布：TXD（即15脚）是SDA，RXD（即16脚）是SCL，官方Pinout和基础外设开发教程中都是对的，例程的Kconfig不
对。虽然对于程序，搞反了也无所谓，但画原理图时就要格外注意
*/
#include "../../../../include/driver/pinctrl.h"
#include "../../../../kernel/osal/include/soc_osal.h"
#include "../../../../include/driver/i2c.h"
#include "../../../../include/driver/gpio.h"
#include "../../../../kernel/osal/include/debug/osal_debug.h"
#include "../../../../kernel/liteos/liteos_v208.5.0/Huawei_LiteOS/open_source/CMSIS/CMSIS/RTOS2/Include/cmsis_os2.h"
#include "../../../../middleware/utils/app_init/app_init.h"

#include "temp_mois.h"
#include "main.h"

#define POLYNOMIAL_CXDZ 0x31 //多项式校验码：X^8 + X^5 + X^4 + 1

uint8_t temp_mois_buff[6];//参数显示缓存数组
int temp = 0;
uint16_t humi = 0;

void SHT30_init(void)
{
    /* I2C pinmux. */
    uapi_pin_set_mode(CONFIG_SHT30_IIC_SCL_PIN, PIN_MODE_2);
    uapi_pin_set_mode(CONFIG_SHT30_IIC_SDA_PIN, PIN_MODE_2);       
    uapi_pin_set_pull(CONFIG_SHT30_IIC_SCL_PIN, PIN_PULL_TYPE_UP);
    uapi_pin_set_pull(CONFIG_SHT30_IIC_SDA_PIN, PIN_PULL_TYPE_UP);
    uapi_i2c_master_init(CONFIG_I2C_MASTER_BUS_ID, I2C_SET_BAUDRATE, I2C_MASTER_ADDR);
    osal_printk("SHT30 init succ\r\n");
}

uint32_t SHT30_IIC_SendData(uint8_t *temp_mois_buffer, uint32_t size)
{
    i2c_data_t data = {0};
    data.send_buf = temp_mois_buffer;
    data.send_len = size;
    uint32_t retval = uapi_i2c_master_write(CONFIG_I2C_MASTER_BUS_ID, SHT30_IIC_ADDRESS, &data);
    if (retval != 0)
    {
        osal_printk("I2cSend failed, %0X!\r\n", retval);
    }
    return retval;
}

uint32_t SHT30_IIC_read_data(uint8_t RegAddress)
{
    i2c_data_t data = {0};

    data.send_buf = &RegAddress;
    data.send_len = sizeof(RegAddress);
    uapi_i2c_master_write(I2C_BUS_1, SHT30_IIC_ADDRESS, &data);//发送要读的寄存器后要重新生成起始命令

    data.send_buf = NULL;
    data.send_len = 0;
    data.receive_buf = temp_mois_buff;
    data.receive_len = sizeof(temp_mois_buff);
    uint32_t retval = uapi_i2c_master_read(CONFIG_I2C_MASTER_BUS_ID, SHT30_IIC_ADDRESS, &data);
    if (retval != 0)
    {
        osal_printk("I2cRead failed, %0X!\r\n", retval);
    }
    return retval;
}

void SHT30_CMD(void)
{
    uint8_t command_H = (SHT30_READ_HUMITURE >> 8) & 0xff;
    uint8_t command_L = SHT30_READ_HUMITURE & 0xff;
    uint8_t send_buff[] = {command_H, command_L};
    SHT30_IIC_SendData(send_buff, sizeof(send_buff));
    osal_msleep(50);//命令发完后需要等待20ms以上才能读写
}

//SHT3X CRC校验
unsigned char SHT3X_CRC(uint8_t *data, uint8_t len)
{
	uint8_t bit;        // bit mask
	uint8_t crc = 0xFF; // calculated checksum
	uint8_t byteCtr;    // byte counter
 
	// calculates 8-Bit checksum with given polynomial @GZCXDZ
	for(byteCtr = 0; byteCtr < len; byteCtr++)
    {
        crc ^= (data[byteCtr]);
        for(bit = 8; bit > 0; --bit)
        {
            if(crc & 0x80)
            {
                crc = (crc << 1) ^ POLYNOMIAL_CXDZ;
            }
            else
            {
                crc = (crc << 1);
            }
        }
	}
    return crc;
}
 
//SHT30读取温湿度
//temp:温度，-400~1250，实际温度=temp/10,分辨率0.1℃,精度±0.3℃
//humi:湿度，0~1000，实际湿度=humi/10,分辨率0.1%rh,精度±3
//返回0成功，1失败
void SHT30_Read_Humiture(void)
{
	SHT30_CMD();//读温湿度命令
	
	SHT30_IIC_read_data(0x01);
	
	//CRC校验
	if(SHT3X_CRC(&temp_mois_buff[0], 2) == temp_mois_buff[2] 
        && SHT3X_CRC(&temp_mois_buff[3], 2) == temp_mois_buff[5])
	{
        /*这里把数据装进sle的发送缓冲区里，如果单纯想要读温湿度然后显示的话可以删掉*/
        osal_printk("read succ\r\n");
        temp = (-45 + (175 * ((temp_mois_buff[0] << 8) + temp_mois_buff[1]) / 65535));
        humi = 100 * ((temp_mois_buff[3] << 8) + temp_mois_buff[4]) / 65535;

        if(temp > 12500)
            temp = 12500;
        else if (temp < -4000)
            temp=-4000;

        sle_tx_buff[TEMP - 3] = (uint8_t)((temp >> 20) & 0xFF);
        sle_tx_buff[TEMP - 3 + 1] = (uint8_t)((temp >> 16) & 0xFF);
        sle_tx_buff[TEMP - 3 + 2] = (uint8_t)((temp >> 8) & 0xFF);
        sle_tx_buff[TEMP - 3 + 3] = (uint8_t)(temp & 0xFF);

        sle_tx_buff[MOIS - 3] = (uint8_t)((humi >> 20) & 0xFF);
        sle_tx_buff[MOIS - 3 + 1] = (uint8_t)((humi >> 16) & 0xFF);
        sle_tx_buff[MOIS - 3 + 2] = (uint8_t)((humi >> 8) & 0xFF);
        sle_tx_buff[MOIS - 3 + 3] = (uint8_t)(humi & 0xFF);

        osal_printk("temp:%d, humi:%d\r\n", temp, humi);
	}
}
